<?
/**
 * This file is part of XNAT light.
 *
 * XNAT light is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * XNAT light is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XNAT light.  If not, see <http://www.gnu.org/licenses/>.
 */
namespace NRG\Framework\Controllers;

use NRG\Framework\Common\Registry as Registry;
use NRG\Database\Mappers as Mappers;

/**
 * Subject controller
 *
 * @package NRG\Framework\Controllers
 */
class Subject extends BaseController
{
    /**
     * XNAT object
     *
     * @var Xnat
     */
    protected $_xnat;

    /**
     * Pre-dispatch of action
     */
    public function preDispatch()
    {
	$this->_xnat = Registry::get("xnat");
    }

    /**
     * Get Subject ID action
     */
    public function idAction()
    {
	if($this->_session->hasRequestParam("like"))
	{
	    $wildcard = $this->_session->getRequestParam("like", false);

	    if(trim($wildcard) == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "wildcard cannot be empty";
		return;
	    }

	    // thwart illegal characters
	    if(!$this->validateWildcard($wildcard))
		return;

	    $wildcard = str_replace("*", "%", $wildcard);
	    $wildcard = str_replace("_", "\_", $wildcard);

	    $mapper = new Mappers\Subject();
	    $vals = $mapper->getWildcardIDs($wildcard);

	    if($vals)
		$this->_view->vals = $vals;
	    else
		$this->_view->vals = array();
	}
	else if($this->_session->hasRequestParam("label"))
	{
	    $label = $this->_session->getRequestParam("label", false);

	    if(trim($label) == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "label cannot be empty";
		return;
	    }

	    $mapper = new Mappers\Subject();
	    $aids = $mapper->getAccessionIDs($label);

	    if($aids)
		$this->_view->vals = $aids;
	    else
		$this->_view->vals = array();
	}
	else
	{
	    $this->_view->error = true;
	    $this->_view->message = "must provide a wildcard or label";
	}
    }

    /**
     * Get Subject label given ID
     */
    public function labelAction()
    {
	if($this->_session->hasRequestParam("like"))
	{
	    $wildcard = $this->_session->getRequestParam("like", false);

	    if(trim($wildcard) == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "wildcard cannot be empty";
		return;
	    }

	    // thwart illegal characters
	    if(!$this->validateWildcard($wildcard))
		return;

	    $wildcard = str_replace("*", "%", $wildcard);
	    $wildcard = str_replace("_", "\_", $wildcard);

	    $mapper = new Mappers\Subject();
	    $labels = $mapper->getWildcardLabels($wildcard);

	    if($labels)
		$this->_view->vals = $labels;
	    else
		$this->_view->vals = array();
	}
	else if($this->_session->hasRequestParam("id"))
	{
	    $id = $this->_session->getRequestParam("id", false);

	    if(trim($id) == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "id cannot be empty";
		return;
	    }

	    $mapper = new Mappers\Subject();
	    $labels = $mapper->getLabel($id);

	    if($labels)
		$this->_view->vals = array($labels);
	    else
		$this->_view->vals = array();
	}
	else
	{
	    $this->_view->error = true;
	    $this->_view->message = "must provide a wildcard or id";
	}
    }

    /**
     * Get the MrSession's project name and id, given an accession id
     */
    public function projectNameAction()
    {
        if(!$this->_session->hasRequestParam('id'))
        {
            $this->_view->error = true;
            $this->_view->message = "must provide an accession id";

            return;
        }

        $id = $this->_session->getRequestParam('id');

        $mapper = new Mappers\Subject();
        $subject = $mapper->byId($id);

        $project = $subject->getProject();

        $this->_view->vals = Array(Array(
                "id" => $project->getID(),
                "name" => $project->getProjectName()
            )
        );
    }

    /**
     * Get Subject experiment IDs
     */
    public function experimentsAction()
    {
	$xnat = Registry::get("xnat");
	$id = "";

	if($this->_session->hasRequestParam("label"))
	{
	    $label = $this->_session->getRequestParam("label");

	    $label = trim($label);

	    if($label == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "label cannot be empty";
		
		return;
	    }

	    $ids = $xnat->getSubjectID($label);

	    if(sizeof($ids) == 0)
	    {
		$this->_view->vals = array();
		
		return;
	    }
	    else if(sizeof($ids) > 1)
	    {
		$this->_view->error = true;
		$this->_view->message = "found multiple subjects";
		
		return;
	    }

	    $id = $ids[0];
	}
	else if($this->_session->hasRequestParam("id"))
	{
	    $id = $this->_session->getRequestParam("id");

	    $id = trim($id);
	    
	    if($id == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "id cannot be empty";
		
		return;
	    }
	}
	else
	{
	    $this->_view->error = true;
	    $this->_view->message = "must provide a label or id";

	    return;
	}

	$subject = $xnat->getSubject($id);

	if($subject == null)
	{
	    $this->_view->vals = array();

	    return;
	}

	$this->_view->vals = $subject->getExperimentIDs();
    }

    /**
     * Get Subject insert info IDs
     */
    public function getInsertInfoAction()
    {
	$xnat = Registry::get("xnat");
	$id = "";

	if($this->_session->hasRequestParam("id"))
	{
	    $id = trim($this->_session->getRequestParam("id"));

	    if(empty($id))
	    {
		$this->_view->error = true;
		$this->_view->message = "id cannot be empty";
		
		return;
	    }
	}

    	$mapper = new Mappers\Subject();
    	$this->_view->vals = $mapper->getInsertInfo($id);
    }



    /**
     * Get Subject info given a Subject ID or Subject label and Project ID
     *
     * $_REQUEST["id"]
     * $_REQUEST["label"] and $_REQUEST["project"]
     */
    public function infoAction()
    {
	if($this->_session->hasRequestParam("id"))
	{
	    $id = $this->_session->getRequestParam("id");

	    $id = trim($id);

	    if($id == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "id cannot be empty";

		return;
	    }

	    $mapper = new Mappers\Subject();
	    $result = $mapper->infoByID($id);

	    $info = array();

	    if($result)
	    {
		$info = array("accession_id" => $result["aid"], "label" => $result["label"],
		    "project_id" => $result["pid"], "project_label" => $result["plabel"]);
	    }

	    $this->_view->vals = $info;
	}
	else if($this->_session->hasRequestParam("label"))
	{
	    $label = trim($this->_session->getRequestParam("label"));

	    if(label == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "label cannot be empty";

		return;
	    }

	    if(!$this->_session->hasRequestParam("project"))
	    {
		$this->_view->error = true;
		$this->_view->message = "you must also provide a project";

		return;
	    }

	    $project = trim($this->_session->getRequestParam("project"));

	    if($project == "")
	    {
		$this->_view->error = true;
		$this->_view->message = "project cannot be empty";

		return;
	    }

	    $mapper = new Mappers\Subject();
	    $result = $mapper->infoByLabel($label, $project);

	    $info = array();

	    if($result)
	    {
		$info = array("accession_id" => $result["aid"], "label" => $result["label"],
		    "project_id" => $result["pid"], "project_label" => $result["plabel"]);
	    }
	    
	    $this->_view->vals = $info;
	}
	else
	{
	    $mapper = new Mappers\Subject();
	    $result = $mapper->infoById();

	    $info = array();

	    foreach($result as $row)
	    {
		$info[] = array("accession_id" => $row["aid"], "label" => $row["label"],
		    "project_id" => $row["pid"], "project_label" => $row["plabel"]);
	    }

	    $this->_view->vals = $info;
	}
    }

    /**
     * Check wildcard for illegal characters
     *
     * @param string $wildcard
     * @return boolean
     */
    private function validateWildcard($wildcard)
    {
	if(!is_string($wildcard))
	    throw new IllegalArgumentException("Wildcard must be an instance of string");
	else if(trim($wildcard) == "")
	    throw new IllegalArgumentException("Wildcard cannot be empty");

	if(preg_match("/^[a-zA-Z0-9_\*]+$/", $wildcard))
	    return true;
	else
	{
	    $this->_view->error = true;
	    $this->_view->message = "wildcard contains illegal characters";

	    return false;
	}
    }

    public function setDateAddedAction()
    {
        $this->adminOnly();

        $project=trim($this->_session->getRequestParam('project'));
        $label=trim($this->_session->getRequestParam('label'));
        $date=trim($this->_session->getRequestParam('date'));

        if (empty($project))
        {
            $this->_view->error=true;
            $this->_view->message="Project must be specified";
            return false;
        }

        if (empty($label))
        {
            $this->_view->error=true;
            $this->_view->message="Label must be specified";
            return false;
        }

        if (empty($date))
        {
            $this->_view->error=true;
            $this->_view->message="Date must be specified";
            return false;
        }

        $ids=$this->_xnat->getSubjectID($label,$project);

        if (!count($ids))
        {
            $this->_view->error=true;
            $this->_view->message="Unable to find a subject with label '$label' in project '$project'";
            return false;
        }

        $id=$ids[0];

        $subject=$this->_xnat->getSubject($id);

        if (empty($subject))
            throw new Exception("Unable to retrieve subject '$label'");

        $mapper = new Mappers\Subject();

	    $result = $mapper->setDateAdded($id,$date);
    }

    public function setAddedByUserAction()
    {
        $this->adminOnly();

        $project=trim($this->_session->getRequestParam('project'));
        $label=trim($this->_session->getRequestParam('label'));
        $login=trim($this->_session->getRequestParam('user'));

        if (empty($project))
        {
            $this->_view->error=true;
            $this->_view->message="Project must be specified";
            return false;
        }

        if (empty($label))
        {
            $this->_view->error=true;
            $this->_view->message="Label must be specified";
            return false;
        }

        if (empty($login))
        {
            $this->_view->error=true;
            $this->_view->message="User login must be specified";
            return false;
        }

        $ids=$this->_xnat->getSubjectID($label,$project);

        if (!count($ids))
        {
            $this->_view->error=true;
            $this->_view->message="Unable to find a subject with label '$label' in project '$project'";
            return false;
        }

        $id=$ids[0];

        //Fetch the subject
        $subject=$this->_xnat->getSubject($id);

        if (empty($subject))
            throw new Exception("Unable to retrieve subject '$label'");

        //Fetch the user
        $mapper = new Mappers\User();
        $user   = $mapper->getUserByLogin($login);

        if ($user===false)
            throw new Exception("No such user exists: $login");

        $mapper = new Mappers\Subject();
	    $result = $mapper->setAddedByUser($id,$user->getID());
    }

}
